package model.algorithms.splitting;

import model.components.networks.virtual.VirtualNetwork;

public class IteratedLocalSearch2 extends SplittingAlgorithm
{
	public IteratedLocalSearch2( String name )
	{
		super( name );
	}
	
	@Override
	protected int[] bestNodesMapping()
	{
		VirtualNetwork requestNetwork = this.getVirtualNetwork();
		double nodesMappingCost[][] = this.getNodesMappingCost();
		int requestNodesNumber = requestNetwork.getNodes().size();
		int substrateNetworksNumber = this.getSdnNetworks().size();
		int nodesMapping[] = new int[ requestNodesNumber ];
		
		for( int j = 0; j < requestNodesNumber; j++ )
		{
			double minNodesMappingCost = Integer.MAX_VALUE;
			
			for( int i = 0; i < substrateNetworksNumber; i++ )
				if( nodesMappingCost[ i ][ j ] < minNodesMappingCost )
				{
					minNodesMappingCost = nodesMappingCost[ i ][ j ];
					nodesMapping[ j ] = i;
				}
		}
		
		int trialsNumber = 10 * substrateNetworksNumber * requestNodesNumber;
		nodesMapping = this.nodesMapping( nodesMapping, trialsNumber );
		
		int maxExperimentsNumber = 5;
		int bestNodesMapping[] = new int[ requestNodesNumber ];
		double bestNetworkMappingCost = Integer.MAX_VALUE;
		
		for( int g = 0; g < maxExperimentsNumber; g++ )
		{
			int perturbation_strength = ( int )Math.round( 0.7 * requestNodesNumber );
			
			for( int i = 0; i < perturbation_strength; i++ )
				nodesMapping[ i ] = ( int )( Math.random() * substrateNetworksNumber );
			
			nodesMapping = this.nodesMapping( nodesMapping, trialsNumber );
			
			double networkMappingCost = this.networkMappingCost( nodesMapping );
			
			if( networkMappingCost < bestNetworkMappingCost )
			{
				bestNetworkMappingCost = networkMappingCost;
				bestNodesMapping = nodesMapping.clone();
			}
		}

		return bestNodesMapping;
	}
	
}